#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

class Request
{
public:
    Request()
    {
    }

    // 序列 反序列化对象
    bool Serializ(std::string *out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::StyledWriter writer;
        *out = writer.write(root);
        if (out->empty())
            return false;
        return true;
    }

    bool Deserialize(std::string &in)
    {
        Json::Reader reader;
        Json::Value droot;
        bool ret = reader.parse(in, droot);
        if (!ret)
            return false;
        _x = droot["x"].asInt();
        _y = droot["y"].asInt();
        _oper = droot["oper"].asInt();
        return true;
    }
    int X()
    {
        return _x;
    }

    int Y()
    {
        return _y;
    }

    char Oper()
    {
        return _oper;
    }
    ~Request()
    {
    }

public:
    //  约定
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response() : _result(0), _code(0)
    {
    }
    bool Serializ(std::string *out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StyledWriter writer;
        *out = writer.write(root);
        if (out->empty())
            return false;
        return true;
    }

    bool Deserialize(std::string &in)
    {
        Json::Reader reader;
        Json::Value droot;
        bool ret = reader.parse(in, droot);
        if (!ret)
            return false;
        _result = droot["result"].asInt();
        _code = droot["code"].asInt();
        return true;
    }

    void SetResult(int r)
    {
        _result = r;
    }
    void SetCode(int c)
    {
        _code = c;
    }
    void Print()
    {
        std::cout << _result << "[" << _code << "]" << std::endl;
    }
    ~Response()
    {
    }

private:
    int _result;
    int _code;
};

bool DigitSafeCheck(const std::string &str)
{
    for (int i = 0; i < str.size(); i++)
    {
        if (!(str[i] > '0' && str[i] <= '9'))
        {
            return false;
        }
    }
    return true;
}

static const std::string sep = "\r\n";

class Protocol
{
public:
    static std::string Package(const std::string &jsonstr)
    {
        // jsonstd -> len\r\njsonstr\r\n
        if (jsonstr.empty())
        {
            return std::string();
        }
        std::string jsonlen = std::to_string(jsonstr.size());
        return jsonlen + sep + jsonstr + sep;
    }

    static int UnPackage(std::string &origin_str, std::string *package)  // 输入输出
    {
        if (package == nullptr)
            return -2;
        auto pos = origin_str.find(sep);
        if (pos == std::string::npos)
        {
            return 0;
        }
        std::string len_str = origin_str.substr(0, pos);
        if (!DigitSafeCheck(len_str))
        {
            return -1;
        }
        int digit_len = std::stoi(len_str);

        int target_len = len_str.size() + digit_len + 2 * sep.size();
        if (origin_str.size() < target_len)
        {
            return 0;
        }

        *package = origin_str.substr(pos + sep.size(), digit_len);
        origin_str.erase(0, target_len);  //  移除

        return package->size();
    }
};